package com.sha.mumbailocal.server.impl;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.sha.mumbailocal.shared.Pair;
import com.sha.mumbailocal.server.exception.ConfigurationException;
import com.sha.mumbailocal.server.intf.IContentDataObjectCollection;
import com.sha.mumbailocal.server.intf.IContentTransformer;
import com.sha.mumbailocal.server.model.intf.IPersistentObject;
import com.sha.mumbailocal.util.BeanPropertyUtil;

public class ContentToPersistentObjectTransformer implements
		IContentTransformer {

	private List<Pair<String, Map<String, String>>> pairs;

	public ContentToPersistentObjectTransformer(
			List<Pair<String, Map<String, String>>> pairs) {
		this.pairs = pairs;
	}

	@Override
	public Collection<IPersistentObject> transform(
			IContentDataObjectCollection contentDataObjectCollection)
			throws ConfigurationException {

		List<Map<String, String>> fieldValues = contentDataObjectCollection
				.getFieldValues();

		Map<String, IPersistentObject> iPersistentObjects = new HashMap<String, IPersistentObject>();

		int row=0;
		for (Map<String, String> map : fieldValues) {

			for (Pair<String, Map<String, String>> pair : pairs) {
				String className = pair.getLeft();
				try {
					String[] s = className.split("\\$");
					Class objectClass = Class.forName(s[0]);
					Map<String, PropertyDescriptor> descriptors = BeanPropertyUtil
							.loadDescriptorMap(objectClass);
					IPersistentObject object = (IPersistentObject) objectClass
							.newInstance();

					Map<String, String> mappings = pair.getRight();

					for (String mappingContent : mappings.keySet()) {
						String mappingDataObject = mappings.get(mappingContent);
						PropertyDescriptor descriptor = descriptors
								.get(mappingContent);
						Object val;
						if (mappingDataObject.charAt(0) == '$') {
							Object obj = iPersistentObjects
									.get(mappingDataObject.substring(1)+"{"+row+"}");
							Method method = null;
							try {
								method = obj.getClass().getMethod("getKey");
							} catch (SecurityException e) {
								e.printStackTrace();
							} catch (NoSuchMethodException e) {
								e.printStackTrace();
							}
							val = method.invoke(obj);
						} else {
							val = BeanPropertyUtil.convertValue(
									map.get(mappingDataObject), descriptor);
						}

						descriptor.getWriteMethod().invoke(object, val);
					}

					iPersistentObjects.put(s[1]+"{"+row+"}", object);
				} catch (InstantiationException e) {
					throw new ConfigurationException(e.getMessage(), e);
				} catch (IllegalAccessException e) {
					throw new ConfigurationException(e.getMessage(), e);
				} catch (ClassNotFoundException e) {
					throw new ConfigurationException(e.getMessage(), e);
				} catch (IntrospectionException e) {
					throw new ConfigurationException(e.getMessage(), e);
				} catch (InvocationTargetException e) {
					throw new ConfigurationException(e.getMessage(), e);
				}
			}
			
			row++;
		}
		return iPersistentObjects.values();
	}

	public void setMaps(List<Pair<String, Map<String, String>>> pairs) {
		this.pairs = pairs;
	}

}
